#include "Semaphore.h"
#include "File.h"
#include "ConfigFile.h"
#include "listdir.h"
#include "enginedirs.h"
#include "Video.h"
#include "TextureManager.h"
#include "engine_global.h"
#include "KeyboardManager.h"
#include "InputManager.h"
#include "Renderer.h"
#include "Cursor.h"
#include "FontManager.h"
#include "Font.h"
#include "Color.h"
#include "SkinManager.h"
#include "UIRenderer.h"
#include "UILabel.h"
#include "UIFile.h"
#include "UICallback.h"
#include "SGNode.h"

#include <iostream>
#include <cmath>
#include <glu.h>

using namespace std;
using namespace Lame3d;

bool running = true;

class EQuit : public KeyboardCallback
{
	public:
		EQuit()
				: KeyboardCallback("quit")
		{
		}
		
		void KeyboardEvent(const KeyEvent &e)
		{
			printf("Quit!\n");
			running = false;
		}
};

class Switcher : public UICallback
{
	public:
		Switcher(UIRenderer &r, UISkin &sh, UISkin &tr)
				: UICallback("SkinSwitcher"), renderer(r), shadowedSkin(sh), transparentSkin(tr)
		{
		}
		
		~Switcher()
		{
		}
		
		void Handle(Window &w, UIElement &e, const std::string &m)
		{
			if(m == "ShadowedTheme") {
				renderer.CurrentSkin() = shadowedSkin.GetHandle();
			} else if(m == "TransparentTheme")
			{
				renderer.CurrentSkin() = transparentSkin.GetHandle();
			}
		}
		
	protected:
		UIRenderer &renderer;
		UISkin &shadowedSkin;
		UISkin &transparentSkin;
};

class CWindow : public UICallback
{
	public:
		CWindow(UIManager &m)
				: UICallback("CloseWindow"), manager(m)
		{
		}
		
		~CWindow()
		{
		}
		
		void Handle(Window &w, UIElement &e, const std::string &m)
		{
			if(m == "CloseWindow") {
				manager.RemoveWindow(&w);
			}
		}
		
	protected:
		UIManager &manager;
};

int main(int argc, char **argv)
{
	EngineInit();
	
	File f("balls");
	cout << "User: " << f.GetUserPath() << endl;
	cout << "System: " << f.GetSystemPath() << endl;
	if(f.UserExists()) {
		cout << "User file exists!" << endl;
	}
	if(f.SystemExists()) {
		cout << "System file exists!" << endl;
	}
	cout << "LameEngine system path: " << getSystemDir() << endl;
	
//	try {
		try {
			DisplayManager dm;
			FontManager fm(dm);
			SkinManager sm(fm, dm);
			InputManager im(dm);
			im.Keyboard().RegisterCallback(new EQuit());
			im.Keyboard().BindCallback(KeyEvent(SDLK_ESCAPE, KMOD_NONE, false), "quit");
			im.UI().RegisterCallback(new CWindow(im.UI()));
			
			UIRenderer uiRender(im, dm, sm);
			uiRender.DisplayFPS(true);
			
			im.UI().RegisterCallback(new Switcher(uiRender,
				sm["Default"], sm["WoW"]));
			
			UIFile uif("UIFiles/About.ui");
			Window *w = uif.GenerateWindow();
			im.UI().AddWindow(w);
			
			UIFile uif2("UIFiles/Stretch.ui");
			im.UI().AddWindow(uif2.GenerateWindow());
			
			UIFile switcherWindow("UIFiles/SkinSwitch.ui");
			im.UI().AddWindow(switcherWindow.GenerateWindow());
			
			UIFile textEntryTest("UIFiles/TextEntryTest.ui");
			im.UI().AddWindow(textEntryTest.GenerateWindow());
			
			TextureManager tm;
			Texture::Handle h = tm["logo.png"].GetHandle();
			
			float t = 0;
			
			glClearColor(0, 0, .3, 0);
			
			while(running) {
				
				glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
				im.Handle();
				t += .5;
				
				glMatrixMode(GL_PROJECTION);
				glLoadIdentity();
				gluPerspective(90, dm.Ratio(), 1, 100);
				
				glMatrixMode(GL_MODELVIEW);
				glLoadIdentity();
				glTranslatef(0, 0, -3);
				glRotatef(25, 1, 0, 0);
				glRotatef(t, 0, 1, 0);
				glColor4f(1, 1, 1, 1);
				h.Bind2d();
				glBegin(GL_QUADS);
					glTexCoord2f(0, 1);
					glVertex3f(-.8, .8, .8);
					glTexCoord2f(0, 0);
					glVertex3f(-.8, -.8, .8);
					glTexCoord2f(1, 0);
					glVertex3f(.8, -.8, .8);
					glTexCoord2f(1, 1);
					glVertex3f(.8, .8, .8);
				glEnd();
				
				glRotatef(90, 0, 1, 0);
					
				glBegin(GL_QUADS);
					glTexCoord2f(0, 1);
					glVertex3f(-.8, .8, .8);
					glTexCoord2f(0, 0);
					glVertex3f(-.8, -.8, .8);
					glTexCoord2f(1, 0);
					glVertex3f(.8, -.8, .8);
					glTexCoord2f(1, 1);
					glVertex3f(.8, .8, .8);
				glEnd();
				
				glRotatef(90, 0, 1, 0);
				
				glBegin(GL_QUADS);					
					glTexCoord2f(0, 1);
					glVertex3f(-.8, .8, .8);
					glTexCoord2f(0, 0);
					glVertex3f(-.8, -.8, .8);
					glTexCoord2f(1, 0);
					glVertex3f(.8, -.8, .8);
					glTexCoord2f(1, 1);
					glVertex3f(.8, .8, .8);
				glEnd();
				
				glRotatef(90, 0, 1, 0);
				
				glBegin(GL_QUADS);	
					glTexCoord2f(0, 1);
					glVertex3f(-.8, .8, .8);
					glTexCoord2f(0, 0);
					glVertex3f(-.8, -.8, .8);
					glTexCoord2f(1, 0);
					glVertex3f(.8, -.8, .8);
					glTexCoord2f(1, 1);
					glVertex3f(.8, .8, .8);
				glEnd();
				glLoadIdentity();
				
				uiRender.RenderUI();
			
				SDL_GL_SwapBuffers();
			}
		} catch(const char *c) {
			cout << "Terminated with: " << c << endl;
		}
		printf("still alive!\n");
		
	SGNode root("root");
	SGNode *child1 = new SGNode("child1");
	child1->Displacement() = CalVector(1, 0, 0);
	child1->Rotation() = CalQuaternion(0, 0, 1, 0);
	SGNode *child2 = new SGNode("child2");
	child2->Displacement() = CalVector(0, 2, 0);
	root.AddChild(child1);
	child1->AddChild(child2);
	
	const CalVector &c = child2->AbsoluteDisplacement();
	printf("Absolute: %f %f %f\n", c[0], c[1], c[2]);
		
//	} catch(const char *c) {
//		cout << "Terminated with determination as: " << c << endl;
//	}
	return 0;
}

// eof //
